JObj.use('ui');
JObj.use('JDrag');
JObj.use('JAnimate');

!JObj.Plugin && ( JObj.Plugin = {} );
JObj.Plugin.JTrackBar = {};

(function($){

    $.cfg = {};

    $.getCfg = function(r,k,d){
        if(! $.cfg[r]) return d;
        if(! $.cfg[r][k]) return d;
        return $.cfg[r][k];
    }

    /**
     * @param type char H or V,default H
     * @param size int ,if H then width = size,else height = size
     * @param body object parentNode,default document.body
     */
    var TrackBar = function(type,size,body,skin){
        var self = this;

        this.onChange = null;
        this.onChangeComplete = null;
        
        var vars = {
            skin: skin || 'JTrackBarDefault',
            type: (type || 'H').toUpperCase() in {'H':1,'V':1} ? (type || 'H').toUpperCase() : 'H',
            size:size || 100,
            initPos:{x:0,y:0},
            division:{min:0,max:100},
            perDivisionSize:0,
            position:0,
            maxX:null,
            maxY:null
        };
        
        var objs = {
            body : JObj.$(body) || document.body,
            outline:null,
            arrBtnA:null,
            arrBtnB:null,
            trackArea:null,
            pointer:null,
            pointerA:null,
            pointerB:null,
            pointerC:null,
            trackAreaAni:null
        };

        this.getCfg = function(k,d){
            return $.getCfg(vars.skin, k,d);
        }

        var doChange = function(obj,x,y){
            if(vars.type == 'H'){
                vars.position = vars.division.min + (x - vars.initPos.x) / ((objs.trackArea.clientWidth - objs.pointer.clientWidth + self.getCfg('h_pointerA_size',15) + self.getCfg('h_pointerC_size',15)) / Math.abs(vars.division.max - vars.division.min));
            }else{
                vars.position = vars.division.min + (y - vars.initPos.y) / ((objs.trackArea.clientHeight - objs.pointer.clientHeight + self.getCfg('v_pointerA_size',15) + self.getCfg('v_pointerC_size',15)) / Math.abs(vars.division.max - vars.division.min));
            }
            JObj.isFunction(self.onChange) && self.onChange( vars.position );
        }        

        var arrBtn_onclick = function(which){
            
        }

        var trackArea_onclick_process = function(obj,fromRule,toRule){
            doChange(obj,fromRule.left,fromRule.top);
        }
        
        var trackArea_change_complete = function(){
        	JObj.isFunction(self.onChangeComplete) ? self.onChangeComplete(vars.position) : null;
        }

        var trackArea_onclick = function(evt){
            evt = window.event || evt;
            var mPos = JObj.UI.JPos.getEventPos(evt);
            var oPos = JObj.UI.JPos.getAbsPos(objs.trackArea);

            if(!objs.trackAreaAni){
                objs.trackAreaAni = JObj.UI.JAnimate.$(objs.pointer);
                objs.trackAreaAni.onProcess = trackArea_onclick_process;
                objs.trackAreaAni.onComplete = trackArea_change_complete;
            }else
                objs.trackAreaAni.abort();

            if(vars.type == 'H'){
                var x = mPos.x - oPos.x + objs.pointerA.clientWidth - objs.pointerB.clientWidth / 2;
                if(x < vars.initPos.x) x = vars.initPos.x;
                if(x > objs.trackArea.clientWidth + objs.pointerC.clientWidth - objs.pointerB.clientWidth)
                    x = objs.trackArea.clientWidth + objs.pointerC.clientWidth - objs.pointerB.clientWidth;
                objs.trackAreaAni.runFromCurrent({left:x});
            }else{
                var y = mPos.y - oPos.y + objs.pointerA.clientHeight - objs.pointerB.clientHeight / 2;
                if(y < vars.initPos.y) y = vars.initPos.y;
                if(y > objs.trackArea.clientHeight + objs.pointerC.clientHeight - objs.pointerB.clientHeight)
                    y = objs.trackArea.clientHeight + objs.pointerC.clientHeight - objs.pointerB.clientHeight;
                objs.trackAreaAni.runFromCurrent({top:y});
            }
        }

        var mouse_wheel = function(evt){
            var evt = window.event || evt;
            if(evt.detail > 0 || evt.wheelDelta < 0)
                self.setPosition( vars.position + 1 );
            else
                self.setPosition(vars.position - 1 );
        }

        var mouse_wheel_opera = function(evt){
            var obj = evt.srcElement;
            while(obj.parentNode){
                if(obj == objs.outline){
                    mouse_wheel(evt);
                    return;
                }
                obj = obj.parentNode;
            }
        }

        var createOutline = function(){
            objs.outline = JObj.$c("DIV");
            objs.body.appendChild(objs.outline);
            objs.outline.className = vars.skin;
            objs.outline.style.position = 'relative';


            objs.arrBtnA = JObj.$c('DIV');
            objs.outline.appendChild(objs.arrBtnA);
            objs.arrBtnA.onclick = JObj.doFunction(arrBtn_onclick,'A');

            objs.trackArea = JObj.$c('DIV');
            objs.outline.appendChild(objs.trackArea);
            objs.trackArea.onclick = trackArea_onclick;

            objs.arrBtnB = JObj.$c('DIV');
            objs.outline.appendChild(objs.arrBtnB);
            objs.arrBtnB.onclick = JObj.doFunction(arrBtn_onclick,'B');

            objs.pointer = JObj.$c('DIV');
            objs.outline.appendChild(objs.pointer);
            objs.pointer.style.position = 'absolute';
            objs.pointer.style.top = 0;

            objs.pointerA = JObj.$c('DIV');
            objs.pointer.appendChild(objs.pointerA);
            objs.pointerA.className = 'pointerA';

            objs.pointerB = JObj.$c('DIV');
            objs.pointer.appendChild(objs.pointerB);
            objs.pointerB.className = 'pointerB';

            objs.pointerC = JObj.$c('DIV');
            objs.pointer.appendChild(objs.pointerC);
            objs.pointerC.className = 'pointerC';

            if(vars.type == 'H'){
                objs.outline.style.width = vars.size + 'px';
                objs.arrBtnA.className = 'btnLeft';
                objs.trackArea.className = 'trackAreaH';
                objs.arrBtnB.className = 'btnRight';

                objs.pointer.className = 'pointerH';
            }else{
                objs.outline.style.height = vars.size + 'px';
                objs.arrBtnA.className = 'btnUp';
                objs.trackArea.className = 'trackAreaV' ;
                objs.arrBtnB.className = 'btnDown';

                objs.pointer.className = 'pointerV';                
            }
        }

        var calcSize = function(){
            if(vars.type == 'H'){
                objs.trackArea.style.width  = objs.outline.clientWidth - self.getCfg('h_btnA_size',15) - self.getCfg('h_btnB_size',15) + 'px';
                objs.pointer.style.left     = self.getCfg('h_btnA_size',15) - self.getCfg('h_pointerA_size',15) + 'px';
                vars.perDivisionSize        = objs.trackArea.clientWidth / Math.abs(vars.division.max - vars.division.min + 1);
                objs.pointerB.style.width   = vars.perDivisionSize + 'px';
                vars.maxX                   = objs.trackArea.clientWidth + self.getCfg('h_pointerC_size',5) - objs.pointerB.clientWidth
            }else{
                objs.outline.style.width    = objs.arrBtnA.clientWidth + 'px';
                objs.pointer.style.top      = objs.arrBtnA.clientHeight - objs.pointerA.clientHeight + 'px';
                objs.trackArea.style.height = objs.outline.clientHeight - self.getCfg('v_btnA_size',15) - self.getCfg('v_btnB_size',15) + 'px';
                vars.perDivisionSize        = objs.trackArea.clientHeight / Math.abs(vars.division.max - vars.division.min + 1);
                objs.pointerB.style.height  = vars.perDivisionSize + 'px';
                vars.maxY                   = objs.trackArea.clientHeight + self.getCfg('v_pointerC_size',5) - objs.pointerB.clientHeight;
            }
        }

        this.create = function(){
            if(JObj.Browser.ie && JObj.Browser.version <= 6){
                JObj.Style.addRule('.' + vars.skin + ' div','font-size:0');
            }

            createOutline();

            setTimeout(JObj.doFunction(calcSize),0);

            setTimeout(function(){
                //vars.initPos = JObj.UI.JPos.getAbsPos(objs.pointer);
                var pos = JObj.UI.JPos.getRelativePos(objs.pointer,objs.outline);
                vars.initPos = {x:pos.x + self.getCfg('h_pointerA_size',5),y:pos.y + self.getCfg('v_pointerA_size',5)}
                //alert(vars.initPos.toSource())
                if(vars.type == 'H'){
                    objs.pointer.style.left = vars.initPos.x + 'px';
                    JObj.UI.JDrag.setDrag(objs.pointer,true,{lockY:true , minX:vars.initPos.x , maxX:vars.maxX,onDrag:doChange});
                }else{
                    objs.pointer.style.top = vars.initPos.y + 'px';
                    JObj.UI.JDrag.setDrag(objs.pointer,true,{lockX:true , minY:vars.initPos.y , maxY:vars.maxY,onDrag:doChange});
                }
            },0);

            if(JObj.Browser.ie || JObj.Browser.safari){
                objs.outline.onmousewheel = mouse_wheel;
            }else if(JObj.Browser.opera){
                document.onmousewheel = mouse_wheel_opera;
            }else if(JObj.Browser.firefox){
                objs.outline.addEventListener("DOMMouseScroll", mouse_wheel, false);
            }
        }

        this.setDivision = function(min,max){
            vars.division.min = isNaN(min) ? 0 : min;
            vars.division.max = isNaN(max) ? 100 : max;
            vars.perDivisionSize = vars.division.min + Math.abs(vars.division.max - vars.division.min + 1) / objs.trackArea.clientWidth;
        }

        var _setPosition = function(pos){
            if(pos < vars.division.min) pos = vars.division.min;
            if(pos > vars.division.max) pos = vars.division.max;

            var mPos = {};
            var oPos = JObj.UI.JPos.getAbsPos(objs.trackArea);

            if(!objs.trackAreaAni){
                objs.trackAreaAni = JObj.UI.JAnimate.$(objs.pointer);
                objs.trackAreaAni.onProcess = trackArea_onclick_process;
                objs.trackAreaAni.onComplete = trackArea_change_complete;
            }else
                objs.trackAreaAni.abort();

            if(vars.type == 'H'){
                mPos.x = (pos - vars.division.min) * vars.perDivisionSize + JObj.UI.JPos.getAbsPos(objs.trackArea).x;
                var x = mPos.x - oPos.x + self.getCfg('h_pointerA_size',5)
                if(x < vars.initPos.x) x = vars.initPos.x;
                if(x > vars.maxX) x = vars.maxX;

                objs.trackAreaAni.runFromCurrent({left:x});
            }else{
                mPos.y = (pos - vars.division.min) * vars.perDivisionSize + JObj.UI.JPos.getAbsPos(objs.trackArea).y;
                var y = mPos.y - oPos.y + self.getCfg('v_pointerA_size',5);
                if(y < vars.initPos.y) y = vars.initPos.y;

                if(y > vars.maxY) y = vars.maxY;

                objs.trackAreaAni.runFromCurrent({top:y});
            }
        }
        this.setPosition = function(pos){
            setTimeout(JObj.doFunction(_setPosition,pos),0);
        }
    }

    $.getRes = function(p){
        JObj.Loader.includeOnce(JObj.path + '/plugins/JTrackBar/' + p + '/config.js');
        JObj.Loader.loadCss(JObj.path + '/plugins/JTrackBar/' + p + '/skin.css');
    }

    $.getInstance = function(type,size,body,skin){
        !skin && (skin = 'JTrackBarDefault');
        $.getRes(skin);
        var tb = new TrackBar(type,size,body);
        return tb;
    }
})(JObj.Plugin.JTrackBar);